You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

109 lines
2.7 KiB

import * as client from 'openid-client';
export default defineEventHandler(async (event) => {
const { config, provider, providerConfig } = await buildOauthConfig(event);
const session = await useWGSession(event);
if (
!session.data.oauth_nonce ||
!session.data.oauth_verifier ||
!session.data.oauth_state
) {
throw createError({
statusCode: 400,
statusMessage: 'Missing OAuth State',
});
}
const currentUrl = getRequestURL(event);
const tokens = await client.authorizationCodeGrant(config, currentUrl, {
pkceCodeVerifier: session.data.oauth_verifier,
expectedNonce:
providerConfig.isOIDC === false ? undefined : session.data.oauth_nonce,
expectedState: session.data.oauth_state,
idTokenExpected: providerConfig.isOIDC ?? true,
});
type SubjectType = string | undefined | typeof client.skipSubjectCheck;
let subject: SubjectType = tokens.claims()?.sub;
if (providerConfig.isOIDC === false) {
subject = client.skipSubjectCheck;
}
if (!subject) {
throw createError({
statusCode: 400,
statusMessage: "Can't get subject",
});
}
let userInfo;
if (providerConfig.userInfoFlow === 'github') {
userInfo = await githubUserInfoFlow(tokens.access_token);
} else {
userInfo = await client.fetchUserInfo(config, tokens.access_token, subject);
}
if (!userInfo.sub) {
throw createError({
statusCode: 400,
statusMessage: 'No sub set',
});
}
if (!userInfo.email) {
throw createError({
statusCode: 400,
statusMessage: 'No email set',
});
}
if (!userInfo.email_verified) {
throw createError({
statusCode: 401,
statusMessage: 'Email is not verified',
});
}
const result = await Database.users.findOrCreateByProvider(
provider,
userInfo.sub,
userInfo.preferred_username || userInfo.email,
userInfo.email,
userInfo.name || 'User'
);
if (!result.success) {
if (result.error === 'USER_DISABLED') {
throw createError({
statusCode: 401,
statusMessage: 'User disabled',
});
}
if (result.error === 'USER_ALREADY_LINKED') {
throw createError({
statusCode: 401,
statusMessage: 'User already linked with different account or provider',
});
}
throw createError({
statusCode: 500,
statusMessage: 'Unexpected error',
});
}
// Create session
const data = await session.update({
userId: result.user.id,
oauth_nonce: undefined,
oauth_state: undefined,
oauth_verifier: undefined,
});
SERVER_DEBUG(
`New OAuth Session: ${data.id} for ${result.user.id} (${result.user.username}) with ${provider}`
);
return sendRedirect(event, '/');
});